
#import "ImageAsset.h"
#import "NSImage+Conversion.h"

@implementation ImageAsset

+ (NSArray *)fileTypes {
    return [NSImage imageFileTypes];
}

- (void)dealloc {
    if (imageProperties) {
        CFRelease(imageProperties);
    }
    if (imageSource) {
        CFRelease(imageSource);
    }
    [super dealloc];
}

- (NSInteger)pixelsWide {
    if (!imageProperties) [self loadMetadata];
    return [[(NSDictionary *)imageProperties valueForKey:(NSString *)kCGImagePropertyPixelWidth] intValue];
}

- (NSInteger)pixelsHigh {
    if (!imageProperties) [self loadMetadata];
    return [[(NSDictionary *)imageProperties valueForKey:(NSString *)kCGImagePropertyPixelHeight] intValue];
}

// Many kinds of image files contain prerendered thumbnail images that can be quickly loaded without having to decode the entire contents of the image file and reconstruct the full-size image.  The ImageIO framework's CGImageSource API provides a means to do this, using the CGImageSourceCreateThumbnailAtIndex() function.  For more information on CGImageSource objects and their capabilities, see the CGImageSource reference on the Apple Developer Connection website, at http://developer.apple.com/documentation/GraphicsImaging/Reference/CGImageSource/Reference/reference.html
- (BOOL)createImageSource {
    if (imageSource == NULL) {
        // Compose absolute URL to file.
        NSURL *sourceURL = [[self url] absoluteURL];
        if (sourceURL == nil) {
            return NO;
        }
        
        // Create a CGImageSource from the URL.
        imageSource = CGImageSourceCreateWithURL((CFURLRef)sourceURL, NULL);
        if (imageSource == NULL) {
            return NO;
        }
        CFStringRef imageSourceType = CGImageSourceGetType(imageSource);
        if (imageSourceType == NULL) {
            CFRelease(imageSource);
            return NO;
        }
        CFRelease(imageSourceType);
    }
    return imageSource ? YES : NO;
}

- (BOOL)loadMetadata {
    if (imageProperties == NULL) {
        if (![self createImageSource]) {
            return NO;
        }
        
        // This code looks at the first image only.  To be truly general, we'd need to handle the possibility of an image source having more than one image to offer us.
        int index = 0;
        imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, index, NULL);
    }
    
    // Return indicating success!
    return imageProperties ? YES : NO;
}

- (BOOL)loadPreviewImage {
    BOOL success;

    if (![self createImageSource]) return NO;

    NSDictionary *options = [[NSDictionary alloc] initWithObjectsAndKeys:
        // Ask ImageIO to create a thumbnail from the file's image data, if it can't find a suitable existing thumbnail image in the file.  We could comment out the following line if only existing thumbnails were desired for some reason (maybe to favor performance over being guaranteed a complete set of thumbnails).
        [NSNumber numberWithBool:YES], (NSString *)kCGImageSourceCreateThumbnailFromImageIfAbsent,
        [NSNumber numberWithInt:160], (NSString *)kCGImageSourceThumbnailMaxPixelSize,
        nil];
    CGImageRef thumbnail = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, (CFDictionaryRef)options);

    NSImage *image = [[NSImage alloc] initWithCGImage:thumbnail];
    [self performSelectorOnMainThread:@selector(setPreviewImage:) withObject:image waitUntilDone:YES];
    success = image ? YES : NO;
    [image release];

    CGImageRelease(thumbnail);
    [options release];

    return success;
}

@end
